package com.lyb269.thread;

import org.junit.Test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Condition通知和等待实现 生产者和消费者
 * 线程之间的协作
 */
public class ConditionWaitAndSignalTest {

    private final ReentrantLock lock = new ReentrantLock();

    private final Condition condition = lock.newCondition();

    //true-表示消费,false-表示生产
    private boolean flag = false;

    //模拟库存指标
    private int store = 0;

    //生产
    private void produce(){
        try{
            lock.lock();
            if (flag){
                //如果是消费,则停止生产
                condition.await();
            }
            System.out.println("生产前库存为:"+store+";生产后库存为:"+(++store));
            flag = !flag;
            //模拟生产一次需耗时2秒
            Thread.sleep(2000);
            //生产完毕,提醒消费
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    //消费
    private void consume(){
        try{
            lock.lock();
            if (!flag){
                //如果生产,则停止消费
                condition.await();
            }
            System.out.println("消费前库存为:"+store+";消费后库存为:"+(--store));
            flag = !flag;
            //模拟消费一次需耗时1.5秒
            Thread.sleep(1500);
            //消费完毕,提醒生产
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    @Test
    public void test(){
        new Thread(() -> {
            //生产线程,一直生产
            while (true){
                produce();
            }
        }).start();

        new Thread(() -> {
            //消费线程,一直消费
            while (true){
                consume();
            }
        }).start();

        //结果如下交替打印:
            //生产前库存为:0;生产后库存为:1
            //消费前库存为:1;消费后库存为:0
            //生产前库存为:0;生产后库存为:1
            //消费前库存为:1;消费后库存为:0
    }

}
